package com.zzyl.nursing.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.constant.Constants;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.thread.UserThreadLocal;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.domain.DeviceData;
import com.zzyl.nursing.domain.Elder;
import com.zzyl.nursing.domain.ElderlyFamilyRelation;
import com.zzyl.nursing.dto.HealthDataDto;
import com.zzyl.nursing.dto.HealthDayDto;
import com.zzyl.nursing.dto.MemberDto;
import com.zzyl.nursing.mapper.DeviceDataMapper;
import com.zzyl.nursing.mapper.ELderFamilyRelationMapper;
import com.zzyl.nursing.mapper.MemUserMapper;
import com.zzyl.nursing.service.IDeviceService;
import com.zzyl.nursing.service.IElderService;
import com.zzyl.nursing.service.MemUserService;
import com.zzyl.nursing.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 小程序端用户接口实现类
 *
 * @Author myl
 * @Date 2025/8/4 21:17
 */
@Service
public class MemUserServiceImpl extends ServiceImpl<MemUserMapper,ElderlyFamilyRelation> implements MemUserService {

    @Autowired
    private IElderService elderService;

    @Autowired
   private MemUserMapper memUserMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IDeviceService deviceService;

    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Autowired
    private ELderFamilyRelationMapper eLderFamilyRelationMapper;


    /**
     * 绑定家人
     */
    @Override
    public void add(MemberDto dto) {
        //1.老人是否存在,并且是否入住
        Elder elder = elderService.getOne(Wrappers.<Elder>lambdaQuery()
                .eq(Elder::getIdCardNo, dto.getIdCard())
                .eq(Elder::getName,dto.getName())
                .ne(Elder::getStatus, 5));
        if(elder == null){
            throw new BaseException("老人信息有误");
        }

        //1.5获取老人家属id
        Long userId = UserThreadLocal.getUserId();


        //2.封装数据
        ElderlyFamilyRelation elderlyFamilyRelation = new ElderlyFamilyRelation();
        elderlyFamilyRelation.setElderId(elder.getId());
        elderlyFamilyRelation.setFamilyId(userId);
        elderlyFamilyRelation.setRemark(dto.getRemark());
        elderlyFamilyRelation.setCreateTime(LocalDateTime.now());
        elderlyFamilyRelation.setCreateBy(String.valueOf(userId));

        //3.新增数据
        boolean save = this.save(elderlyFamilyRelation);
        if(!save){
            throw new BaseException("新增失败");
        }
    }

    /**
     * 查询家人列表
     *
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public List<ElderlyFamilyRelationVo> listPage(Integer pageNum, Integer pageSize) {
        Long userId = UserThreadLocal.getUserId();
        return memUserMapper.list(userId);
    }

    /**
     * 查看家人列表
     *
     * @return
     */
    @Override
    public List<ElderFamilyMyVo> listAll() {
        List<ElderFamilyMyVo> list = memUserMapper.listALl();
        return list;
    }

    /**
     * 解绑
     *
     * @param id
     */
    @Override
    public void deleteById(Long id) {
        eLderFamilyRelationMapper.deleteById(id);

    }

    /**
     * 查看健康数据
     *

     * @return
     */
    @Override
    public HealthDataVo QueryDevicePropertyStatus(HealthDataDto dto) {
        //1.根据传的条件查询该设备的iotId
        Device device = deviceService.getOne(Wrappers.<Device>lambdaQuery()
                .eq(Device::getDeviceName, dto.getDeviceName())
                .eq(Device::getProductKey, dto.getProductKey()));

        if(ObjectUtil.isEmpty(device)){
            throw new BaseException("该设备不存在");
        }

        String iotId = device.getIotId();

        //2.从redis数据库中查询设备属性
        String JSONStr = (String) redisTemplate.opsForHash().get(Constants.IOT_DEVICE_LAST_DATA, iotId);
        List<DeviceData> deviceDataList = JSONUtil.toList(JSONStr, DeviceData.class);

        HealthDataVo healthDataVo = new HealthDataVo();
        healthDataVo.setList(new PropertyStatusInfoList()); // 初始化 list
        List<PropertyStatus> propertyStatusInfo = new ArrayList<>();

        //3.封装
        deviceDataList.forEach(x->{
            PropertyStatus propertyStatus = new PropertyStatus();
            propertyStatus.setDataType("int");
            propertyStatus.setIdentifier(x.getFunctionId());
            // 指定特定时区转换
            long timestampWithSpecificZone = x.getAlarmTime().atZone(ZoneId.of("Asia/Shanghai"))
                    .toInstant()
                    .toEpochMilli();

            propertyStatus.setTime(String.valueOf(timestampWithSpecificZone));

            propertyStatus.setValue(x.getDataValue());
            propertyStatusInfo.add(propertyStatus);
        });

        healthDataVo.getList().setPropertyStatusInfo(propertyStatusInfo); // 设置数据

        //4.返回
        return healthDataVo;


    }

    /**
     * 按天统计查询指标数据
     *
     * @param functionId
     * @param startTime
     * @param endTime
     * @param iotId
     * @return
     */
    @Override
    public List<HealthDayVo> queryDeviceDataListByDay(String functionId, Long startTime, Long endTime, String iotId) {
        LocalDateTime start = Instant.ofEpochMilli(startTime).atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime end = Instant.ofEpochMilli(endTime).atZone(ZoneId.systemDefault()).toLocalDateTime();

        List<Map<String,Object>> list = deviceDataMapper.queryDeviceDataListByDay(functionId, start, end, iotId);
        List<HealthDayVo> voList = new ArrayList<>();
        list.forEach(map ->{
            HealthDayVo healthDayVo = new HealthDayVo();
            healthDayVo.setDateTime((String) map.get("dateTime"));
            healthDayVo.setDataValue(Double.parseDouble((map.get("dataValue")+"")));
            voList.add(healthDayVo);
        });

        return voList;
    }

    /**
     * 按周查询指标数据
     *
     * @param dto
     * @return
     */
    @Override
    public List<HealthDayVo> queryDeviceDataListByWeek(HealthDayDto dto) {
        //1.转换数据类型localdateTime
        LocalDateTime start = Instant.ofEpochMilli(dto.getStartTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime end = Instant.ofEpochMilli(dto.getEndTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();

        //2.查询数据库
        List<HealthDayVo> list = deviceDataMapper.queryDeviceDataListByWeek(dto.getFunctionId(), start, end, dto.getIotId());
        return list;
    }
}
